#include <stdlib.h>
#include <string>
#include <iostream>
#include <rise/common/exmacros.h>
#include <rise/common/Log.h>
#include <rise/common/Exception.h>
#include <rise/common/DataEncoder.h>
#include <staff/common/Value.h>
#include <staff/common/QName.h>
#include <staff/common/Attribute.h>
#include <staff/common/DataObject.h>
#include <staff-mq/client/Message.h>
#include <staff-mq/client/Subscriber.h>

class MyMessageHandler: public smq::MessageHandler
{
public:
  virtual void operator()(smq::Subscriber& rSubscriber, const smq::Message& rMsg)
  {
    const staff::CDataObject& tdoMsg = rMsg.tdoMessage;

    std::cout << "Message arrived: \n"
        << "msgid: " << rMsg.sId << std::endl
        << "queue: " << rMsg.sQueue << std::endl
        << "publisher: " << rMsg.sPublisher << std::endl
        << "message: " << tdoMsg.ToString() << std::endl << std::endl;

    int nVal = tdoMsg["int_val1"];
    int dVal = tdoMsg["double_val1"];
    std::string sVal = tdoMsg["str_val1"].AsString();

    std::cout
        << "int_val: " << nVal << std::endl
        << "double_val: " << dVal << std::endl
        << "string_val: " << sVal << std::endl;

    if (rMsg.sQueue == "test-queue1")
    { // reading attrs
      std::string sAttr = tdoMsg.GetAttributeTextByName("attr_string");
      int nAttr = tdoMsg.GetAttributeValueByName("attr_int");
      double dAttr = tdoMsg.GetAttributeValueByName("attr_double");

      std::cout << std::endl
          << " -- attrs -- :"  << std::endl
          << "string: " << sAttr << std::endl
          << "int: " << nAttr << std::endl
          << "double: " << dAttr << std::endl;
    }
    else
    if ((rMsg.sQueue == "queue1") || (rMsg.sQueue == "queue2"))
    { // reading data
      staff::CDataObject tdoData = tdoMsg.GetChildByLocalName("Data");
      // decoding data
      unsigned char uchData[256]; // incomming data
      unsigned long unDataSize = sizeof(uchData);
      // decoding data from base64 string
      rise::CBase64Encoder::Decode(tdoData.GetText(), uchData, unDataSize);

      std::cout << std::endl << " -- data(" << unDataSize << " bytes) -- :"  << std::endl;
      for (int i = 0; i < 256; ++i)
      {
        std::cout << (static_cast<unsigned int>(uchData[i]) & 0xff) << " ";
      }
      std::cout << std::endl << " -- end data --"  << std::endl;

    }
    else
    {
      rise::LogWarning() << "Unknown Queue: " << rMsg.sQueue;
    }
  }
};


int main(int nArgs, char* szArgs[])
{
  std::string sServerHost = "127.0.0.1";
  unsigned short ushServerPort = 8768;

  for (int nArg = 1; nArg < nArgs; ++nArg)
  {
    if(szArgs[nArg])
    {
      const std::string& sArg = std::string(szArgs[nArg]);
      if (sArg.substr(0, 2) == "-s")
      {
        sServerHost = sArg.substr(2);
      }
      else
      if (sArg.substr(0, 2) == "-p")
      {
        ushServerPort = static_cast<unsigned short>(atoi(sArg.substr(2).c_str()));
      }
      else
      if (sArg.substr(0, 2) == "-h")
      {
        std::cerr << "Subscriber sample.\n\n"
            << szArgs[0] << "[ -h][ -s<Server host>][ -p<port>]\n\n";
        return 0;
      }
      else
      {
        std::cerr << "unknown arg: " << sArg << "\n";
        return 1;
      }
    }
  }

  try
  {
    MyMessageHandler tMessageHandler;

    smq::Subscriber tSubscriber;
    tSubscriber.Init("test_subscriber", sServerHost, ushServerPort);

    tSubscriber.SetHandler(&tMessageHandler);
    std::cout << "subscribing to \"queue*\"" << std::endl;
    tSubscriber.Subscribe("queue*");
    std::cout << "subscribing to \"test-queue1\"" << std::endl;
    tSubscriber.Subscribe("test-queue1");

    tSubscriber.Start();
  }
  RISE_CATCH_ALL

  return 0;
}
